#ifndef _SESSION_H
#define _SESSION_H

struct WorldPacketHandler
{
	void (Session::*method)(RealmPacket&);
	bool need_player;
};

struct Account
{
	ui32 id;
	char* username;
	ui8* passwordhash;
	ui8 sessionkey[40];
	char* gmstring;
	string country;
};

class MovementHandler;

class DLL_EXPORT Session : public CThread
{
	friend class WorldSocket;
	friend class LogonClientHandler;
	friend class LogonClientWorker;
	friend class Player;
	SOCKET m_socket;
	DataBuffer m_readbuffer;
	DataBuffer m_writebuffer;
	Mutex m_cryptlock;
	Mutex m_socketlock;
	WorldPacketHandler* m_handles;
	WowCrypt m_crypt;
	ui32 m_seed, m_clientseed, m_request, m_logouttime;
	RealmPacket* m_authpacket;
	Account* m_account;
	Player* m_player;
	MovementHandler* m_movehandler;
	WoWGuid m_moverguid;
	bool canusez;
	bool canusea;
	set<char> m_commands;

	void AddonRequest();
	void RetrieveInformation(ui8 error, RealmPacket* pack);
	void OnConnect();

	void HandleAuthSession(RealmPacket&);
	void HandleCharEnum(RealmPacket&);
	void HandleCharCreate(RealmPacket&);
	void HandleCharDelete(RealmPacket&);
	void Handle38C(RealmPacket&);
	void HandlePing(RealmPacket&);
	void HandlePlayerLogin(RealmPacket&);
	void HandleChatMessage(RealmPacket&);
	void HandleNameQuery(RealmPacket&);
	void HandleMovement(RealmPacket&);
	void ChangeActiveMover(RealmPacket&);
	void HandleRequestRaidInfo(RealmPacket&);
	void HandleGetGMTicket(RealmPacket&);
	void HandleQueryTime(RealmPacket&);
	void HandleMailBoxTime(RealmPacket&);
	void HandleBattleFieldStatus(RealmPacket&);
	void HandleJoinChannel(RealmPacket&);
	void HandleChannelPeople(RealmPacket&);
	void HandleSetSelection(RealmPacket&);
	void HandleLogoutRequest(RealmPacket&);
	void HandleLogoutCancel(RealmPacket&);
	void HandleCastSpell(RealmPacket&);
	void HandleCreatureQuery(RealmPacket&);
	void HandleGossipHello(RealmPacket&);
	void HandleGossipSelect(RealmPacket&);
	void HandleNpcText(RealmPacket&);
	void HandleItemNameQuery(RealmPacket&);
	void HandleZoneUpdate(RealmPacket&);
	void HandleStandStateChange(RealmPacket&);
	void HandleTaxiList(RealmPacket&);
	void HandleTaxiNodeQuery(RealmPacket&);
	void HandleTaxiStart(RealmPacket&);
	void HandleSetAction(RealmPacket&);
	void HandleGameObjectQuery(RealmPacket&);
	void HandleBindConfirm(RealmPacket&);
	void HandleQuestNpcQuery(RealmPacket&);
	void HandleWorldportAck(RealmPacket&);
	void HandleSetSheathed(RealmPacket&);
	void HandleTrainerBuy(RealmPacket&);
	void HandleMoveTimeSkipped(RealmPacket&);
	void HandleQuestGiverHello(RealmPacket&);
	void HandleQuestQuery(RealmPacket&);
	void HandleQuestAccept(RealmPacket&);
	void HandleQuestNewQuestQuery(RealmPacket&);
	void HandleItemQuerySingle(RealmPacket&);
	void HandleGameObjectUse(RealmPacket&);
	void HandleItemSwap(RealmPacket&);
	void HandleAttackStart(RealmPacket&);
	void HandleAttackStop(RealmPacket&);
	void HandleMsgRoll(RealmPacket&);
	void HandleTaxiExpress(RealmPacket&);
	void HandleUseItem(RealmPacket&);
	void HandleCancelCast(RealmPacket&);
	void HandleSetLfgRole(RealmPacket&);
	void HandleSetLfg(RealmPacket&);
	void HandleLfgAutoJoin(RealmPacket&);
	void HandleLfgClearAutoJoin(RealmPacket&);
	void HandleCalendarAddEvent(RealmPacket&);

	Session();
	~Session();
public:
	void Loop();
	void SendPacket(RealmPacket* pack);
	void SendToSet(RealmPacket* pack, bool self = false);
	void Disconnect();
	ui32 GetAccountId() { if(m_account) return m_account->id; return 0; }
	bool CanUseCommand(char cmd);
	Player* GetPlayer() { return m_player; }
	MovementHandler* GetLastMovement() { return m_movehandler; }
};

#endif